﻿using Application.Services;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Infrastructure.Services.JWT
{
    public class JWTService : IJWTService
    {
        private const string userIdKey = "userId";
        private const string userNameKey = "userName";
        private const string rolesKey = "roles";

        private const string Secret = "666";//TODO  放到config中
        private static readonly SymmetricSecurityKey Key =
        new(Encoding.UTF8.GetBytes(Secret));

        public string GenerateToken(string userId, string userName, ICollection<string> roles)
        {
            var claims = new List<Claim>()
            {
                new(userIdKey,userId),
                new(userNameKey,userName),
            };
            foreach (var item in roles)
                claims.Add(new(rolesKey, item));

            var creds = new SigningCredentials(Key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                claims: claims,
                expires: DateTime.UtcNow.AddMinutes(15),
                signingCredentials: creds
            );

            return new JwtSecurityTokenHandler().WriteToken(token);
        }

        public IEnumerable<string> GetRoles(ClaimsPrincipal principal)
        {
            return principal.FindAll(rolesKey).Select(x => x.Value);
        }

        public string GetUserId(ClaimsPrincipal principal)
        {
            return principal.FindFirst(userIdKey).Value;
        }

        public string GetUserName(ClaimsPrincipal principal)
        {
            return principal.FindFirst(userNameKey).Value;
        }

        public ClaimsPrincipal? ValidateToken(string token)
        {
            var handler = new JwtSecurityTokenHandler();
            try
            {
                return handler.ValidateToken(token, new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = Key,
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    ClockSkew = TimeSpan.Zero
                }, out _);
            }
            catch
            {
                return null;
            }
        }
    }
}
